package com.learning.spring.security.pwd.store.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

import static org.springframework.security.config.Customizer.withDefaults;

/**
 * ClassName: SecurityConfig
 * Description:
 * Date: 2022/7/29 9:14
 *
 * @author Sam Sho
 * @version V1.0.0
 */
@Configuration
public class SecurityConfig {

    /**
     * 1. 将用户重定向到登录表单处理流程
     * - FilterSecurityInterceptor 主要处理该流程，并且抛出 AccessDeniedException
     * - ExceptionTranslationFilter 捕获 AccessDeniedException 异常，交由 LoginUrlAuthenticationEntryPoint 处理，发送一个重定向到 /login
     *
     * 2. 表单登录认证处理流程
     * - AbstractAuthenticationProcessingFilter（UsernamePasswordAuthenticationFilter） 对用户名和密码进行验证
     * - 从请求中获取 UsernamePasswordAuthenticationToken 对象
     * - AuthenticationManager（ProviderManager）进行认证
     *
     * 3. 认证失败 AbstractAuthenticationProcessingFilter#unsuccessfulAuthentication 方法
     * - AuthenticationFailureHandler（SimpleUrlAuthenticationFailureHandler） 处理
     *
     * 4. 认证成功 AbstractAuthenticationProcessingFilter#successfulAuthentication 方法
     * - AuthenticationSuccessHandler（SimpleUrlAuthenticationSuccessHandler ）处理
     * */

    /**
     * 简单的自定义
     *
     * @param http
     * @return
     * @throws Exception
     */
    @Bean
    public SecurityFilterChain filterChain1(HttpSecurity http) throws Exception {
        http.mvcMatcher("/a/**").authorizeRequests().anyRequest().authenticated();
        http.formLogin(withDefaults());
        return http.build();
    }

    /**
     * 框架会有默认的登录页面。
     * 自定义登录表单
     * - 定义 loginPage 属性
     * - 定义 login.html 页面
     * - 定义与 loginPage属性和 login.html页面匹配的控制器 （Controller）
     *
     * @param http
     * @return
     * @throws Exception
     */
    @Bean
    public SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
        http.mvcMatcher("/b/**").authorizeRequests().anyRequest().authenticated();

        http.formLogin(form -> form
                .loginPage("/bLogin")
                .permitAll()
        );
        return http.build();
    }

}
